package com.lance.shiro.service;

import com.lance.shiro.config.PropertySaleStatus;
import com.lance.shiro.entity.IProperty;
import com.lance.shiro.entity.IPropertyList;
import com.lance.shiro.entity.ISalesNotification;
import com.lance.shiro.entity.IUser;
import com.lance.shiro.mapper.PropertyMapper;
import com.lance.shiro.mapper.SalesNotificationMapper;
import com.lance.shiro.mapper.UserMapper;
import com.lance.shiro.utils.ConvertUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Map;

import static com.lance.shiro.config.ConstantVariable.*;

@Service
@Transactional
public class PropertyServiceImpl implements PropertyService {
    public Logger log = LogManager.getLogger(getClass());
    @Autowired
    private PropertyMapper propertyMapper;

    @Autowired
    private CommonService commonService;

    @Autowired
    private UMailService uMailService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SalesNotificationMapper salesNotificationMapper;

    @Autowired
    SalesNotificationService salesNotificationService;


    @Override
    public Map get(int id) {
        IProperty property = propertyMapper.get(id);
        ArrayList<Map> mapArrayList = salesNotificationService.findAllByPropertyId(id);
        property.setSalesNotificationList(mapArrayList);
        return setAttachment(property);
    }

    @Override
    public Map save(IProperty property) throws IllegalAccessException {
        if (property.getId() == 0) {
            propertyMapper.add(property);
        } else {
//            Field fields[] = property.getClass().getDeclaredFields();
//            StringBuffer sb = new StringBuffer();
//            for (int i = 0; i < fields.length; i++) {
//                fields[i].setAccessible(true);
//                String keyName = fields[i].getName();
//                // 处理空值和实体 agent，owner，propertyList
//                if (!keyName.equals("agent") && !keyName.equals("owner") && !keyName.equals("propertyList") && !keyName.equals("qty")) {
//                    String value = fields[i].get(property) == null ? "" : fields[i].get(property).toString();
//                    sb.append(keyName).append("=").append("'").append(fields[i].get(property)).append("'").append(" ").append(",");
//                }
//            }
//            if (null != sb) {
//                String s = sb.toString();
//                propertyMapper.update(property.getId(), s.substring(0, s.length() - 1));
//                property = propertyMapper.get(property.getId());
//            }
            IProperty originProperty = propertyMapper.get(property.getId());
            if (!StringUtils.equals(originProperty.getSale_status(), property.getSale_status())) {
                try {
                    String to = userMapper.getAdminEmail();
                    String subject = String.format("Project:[%s], Lot:[%s]  has changed status", property.getPropertyList().getName(), property.getLot());
                    String body = "<div>" + String.format("Status changed from %s to %s by admin <br>", originProperty.getSale_status(), property.getSale_status()) + "</div>";
                    body += "<div><a href=\"https://ipanproperty.com\" target='_blank'>https://ipanproperty.com</a></div>";

                    uMailService.sendManagerMail(to, subject, body);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (originProperty.getAgentId() != property.getAgentId() && property.getAgentId() == 0) {
                try {
                    String to = userMapper.getAdminEmail() + ";" + originProperty.getAgent().getEmail() + ";" + originProperty.getAgent().getEmail();
                    String subject = String.format("Project:[%s], Lot:[%s]  has been rejected", property.getPropertyList().getName(), property.getLot());
                    String body = "<div>We are sorry that Your SaleNotification Materials haven’t pass our validation. Please collect mandatoryinformation again and submit through website again.<br>";
                    body += "Thanks for your corporation.</div>";
                    body += "<div>Please contact " + userMapper.getAdminEmail() + " if there's any question.</div>";
                    body += "<div><a href=\"https://ipanproperty.com\" target='_blank'>https://ipanproperty.com</a></div>";

                    uMailService.sendManagerMail(to, subject, body);
                } catch (Exception e) {
                    log.error(e);
                }
            }
            propertyMapper.update(property);
        }
        return setAttachment(property);
    }

    @Override
    public void deleteAllByIds(ArrayList<Integer> ids) {
        int size = ids.size();
        for (int i = 0; i < size; i++) {
            delete(ids.get(i));
        }
    }

    @Override
    public ArrayList<Map> findAllByAgents(ArrayList<Integer> agentId) {
        ArrayList<IProperty> list;
        if (agentId != null && agentId.size() > 0) {
            String agentIds = "'" + StringUtils.join(agentId, "','") + "'";
            list = propertyMapper.findAllByAgent(agentIds);
        } else {
            list = propertyMapper.findAll();
        }
        return setAttachmentForList(list);
    }

    @Override
    public ArrayList<Map> findAllByOwners(ArrayList<Integer> ownerId) {
        ArrayList<IProperty> list;
        if (ownerId != null && ownerId.size() > 0) {
            String ownerIds = "'" + StringUtils.join(ownerId, "','") + "'";
            list = propertyMapper.findAllByOwner(ownerIds);
        } else {
            list = propertyMapper.findAll();
        }
//        List<Test> query = baseMysqlCRUDManager.query(test);
        return setAttachmentForList(list);
    }

    /**
     * @param reqMap
     * @return
     */
    @Override
    public ArrayList<Map> findAllByPropertyLists(Map<String, String> reqMap) {
        ArrayList<IProperty> list;
        boolean isFindAll = false;
        if (null != reqMap && reqMap.size() > 0) {
            IProperty iProperty = new IProperty();
            Field fields[] = iProperty.getClass().getDeclaredFields();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < fields.length; i++) {
                String keyName = fields[i].getName();
                if (null != reqMap.get(keyName)) {
                    sb.append("  ").append(keyName).append("=").append("'").append(reqMap.get(keyName)).append("'").append("  ").append("and");
                }
            }
            if (null != sb) {
                String s = sb.toString();
                list = propertyMapper.findAllByPropertyList(s.substring(0, s.length() - 3));
            } else {
                list = propertyMapper.findAll();
                isFindAll = true; //Zhan: Fix performance issue
            }
        } else {
            list = propertyMapper.findAll();
            isFindAll = true; //Zhan: Fix performance issue
        }
        ArrayList<Map> result;
       if (isFindAll) {
           //Zhan: Do not fetch all attachment for find all scenario. It causes slow performance
           result = new ArrayList<Map>();
            for (int i = 0, size = list.size(); i < size; i++) {
               Map mproperty = ConvertUtils.beanToMap(list.get(i));
               result.add(mproperty);
            }
        } else {
           result = setAttachmentForList(list);  //SetAttachment causes major performance issue. Avoid calling this method while findAll()
        }
        return result;
    }

    /**
     * @param id
     * @param reqMap
     * @return
     */
    @Override
    public IProperty updateAttribute(int id, Map<String, String> reqMap) {
        IProperty iProperty = propertyMapper.get(id);
        if (null != iProperty) {
            Field fields[] = iProperty.getClass().getDeclaredFields();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < fields.length; i++) {
                String keyName = fields[i].getName();
                if (null != reqMap.get(keyName)) {
                    sb.append("  ").append(keyName).append("=").append("'").append(reqMap.get(keyName)).append("'").append("  ").append(",");
                }
            }
            if (null != sb) {
                String s = sb.toString();
                propertyMapper.updateAttribute(iProperty.getId(), s.substring(0, s.length() - 1));
                iProperty = propertyMapper.get(id);
                return iProperty;
            }
        }
        return null;
    }

    @Override
    public IProperty notifysale(int id, Map<String, String> reqMap) throws Exception {
        IProperty iProperty = updateAttribute(id, reqMap);

        String to = userMapper.getAdminEmail();
        if (to != null && !to.equals("")) {
            String subject = String.format("Project:[%s], Lot:[%s]  has received a deposit", iProperty.getPropertyList().getName(), iProperty.getLot());
            String body = "<div>Agent: " + iProperty.getAgent().getCode() + " " +
                    iProperty.getAgent().getFirstName() + " " + iProperty.getAgent().getLastName() +
                    " has submitted a property  deposit request for " + String.format("Project:[%s], Lot:[%s]", iProperty.getPropertyList().getName(), iProperty.getLot()) +
                    " at time: " + iProperty.getUpdateTime() + "</div>";
            body += "<div>Sales Notes: " + iProperty.getSale_note() + "</div>";
            body += "<div><a href=\"https://ipanproperty.com\" target='_blank'>https://ipanproperty.com</a></div>";
            uMailService.sendManagerMail(to, subject, body);
        }
        return iProperty;
    }

    @Override
    public IProperty updateStatusSaleNote(Map<String, String> reqMap) throws Exception {
        IProperty iProperty = propertyMapper.get(Integer.valueOf(reqMap.get("id")));
        if (null == iProperty || null == reqMap.get("sale-status") || StringUtils.isBlank(reqMap.get("sale-status").toString())) {
            throw new Exception("The entity is empty!");
        }
        String sale_status = reqMap.get("sale-status");
        // 状态由12变成34，删除其他申请，发送邮件
        if (iProperty.getSale_status().equals(PropertySaleStatus.FOR_SALE) || iProperty.getSale_status().equals(PropertySaleStatus.DEPOSIT_TAKEN)) {
            if (sale_status.equals(PropertySaleStatus.CONTRACT_EXCHANGED) || sale_status.equals(PropertySaleStatus.SETTLED)) {
                // 1.更新property 状态
                propertyMapper.updateStatusSaleNote(Integer.valueOf(reqMap.get("id")), sale_status, iProperty.getSale_note());
                // 2.查询其他申请
                ArrayList<ISalesNotification> salesNotificationArrayList = salesNotificationMapper.findAllByPropertyId(iProperty.getId());
                if (null != salesNotificationArrayList && salesNotificationArrayList.size() > 0) {
                    for (ISalesNotification temp : salesNotificationArrayList) {
                        ISalesNotification sendTemp = salesNotificationMapper.get(temp.getId());
                        // 3.向其他申请发送邮件
                        sendAcceptedMail(sendTemp.getAgent(), sendTemp.getProperty(), sendTemp.getPropertyList());
                        // 4.删除其他申请附件和记录
                        deleteAttachment(temp.getId(), BELONG_TO_CATEGORY_SALES_NOTIFICATION_PROPERTY_BANK_CARD_PICTURE);
                        salesNotificationMapper.delete(temp.getId());
                    }
                }
            }
        }

        // 状态由234变成1，还原数据
        if (iProperty.getSale_status().equals(PropertySaleStatus.DEPOSIT_TAKEN) || iProperty.getSale_status().equals(PropertySaleStatus.CONTRACT_EXCHANGED)
                || iProperty.getSale_status().equals(PropertySaleStatus.SETTLED)) {
            if (sale_status.equals(PropertySaleStatus.FOR_SALE)) {
                // 1.更新状态，同时更新sale note

                propertyMapper.updateStatusSaleNote(Integer.valueOf(reqMap.get("id")), sale_status, "");
                // 2.删除关联的property_bank_card_picture图片
                deleteAttachment(Integer.valueOf(reqMap.get("id")), BELONG_TO_CATEGORY_PROPERTY_BANK_CARD_PICTURE);
            }

        }
        return iProperty;
    }

    private void sendAcceptedMail(IUser user, IProperty property, IPropertyList propertyList) {
        try {
            String subject = "Your application for " + propertyList.getName() + " " + property.getLot() + " has been taken by other member.";
            String body = "<div>Dear " + user.getFirstName() + " " + user.getLastName() + ", </div>";
            body += "<div>Your property sale request for " + propertyList.getName() + " Lot: " + property.getLot() + " with price: </div>";
            body += "<div>  " + property.getSellingPrice() + "  has been taken by other member. </div>";
            body += "<div> Thank you.</div>";
            Map<String, String> ret = uMailService.sendManagerMail(user.getPrivateEmail(), subject, body);
        } catch (Exception ex) {
            log.error(ex);
        }

    }

    private void deleteAttachment(Integer id, String attachmentType) {
        String sid = String.valueOf(id);
        try {
            commonService.deleteListAttachmentByBelong(sid, attachmentType);
        } catch (Exception ex) {
            log.error(ex);
        }

    }


    @Override
    public void delete(Integer id) {
        propertyMapper.delete(id);
        String sid = String.valueOf(id);
        commonService.deleteListAttachmentByBelong(sid, BELONG_TO_CATEGORY_PROPERTY_COS_DOCUMENT);
        commonService.deleteListAttachmentByBelong(sid, BELONG_TO_CATEGORY_PROPERTY_DEPOSIT_FORM_DOCUMENT);
        commonService.deleteListAttachmentByBelong(sid, BELONG_TO_CATEGORY_PROPERTY_BILL_CHARGES);
        commonService.deleteListAttachmentByBelong(sid, BELONG_TO_CATEGORY_PROPERTY_MANAGEMENT_AGREEMENT_DOCUMENT);
        commonService.deleteListAttachmentByBelong(sid, BELONG_TO_CATEGORY_PROPERTY_OTHERS);
        commonService.deleteListAttachmentByBelong(sid, BELONG_TO_CATEGORY_PROPERTY_MAIN_IMAGE);
        commonService.deleteListAttachmentByBelong(sid, BELONG_TO_CATEGORY_PROPERTY_BANK_CARD_PICTURE);
    }

    private ArrayList<Map> setAttachmentForList(ArrayList<IProperty> list) {
        ArrayList<Map> aPropertys = new ArrayList<Map>();
        for (int i = 0, size = list.size(); i < size; i++) {
            Map maProperty = setAttachment(list.get(i));
            aPropertys.add(maProperty);
        }
        return aPropertys;
    }

    private Map setAttachment(IProperty property) {
        Map mproperty = ConvertUtils.beanToMap(property);
        String id = String.valueOf(property.getId());
        mproperty.put(BELONG_TO_CATEGORY_PROPERTY_COS_DOCUMENT, commonService.findListAttachmentByBelong(id, BELONG_TO_CATEGORY_PROPERTY_COS_DOCUMENT));
        mproperty.put(BELONG_TO_CATEGORY_PROPERTY_DEPOSIT_FORM_DOCUMENT, commonService.findListAttachmentByBelong(id, BELONG_TO_CATEGORY_PROPERTY_DEPOSIT_FORM_DOCUMENT));
        mproperty.put(BELONG_TO_CATEGORY_PROPERTY_BILL_CHARGES, commonService.findListAttachmentByBelong(id, BELONG_TO_CATEGORY_PROPERTY_BILL_CHARGES));
        mproperty.put(BELONG_TO_CATEGORY_PROPERTY_MANAGEMENT_AGREEMENT_DOCUMENT, commonService.findListAttachmentByBelong(id, BELONG_TO_CATEGORY_PROPERTY_MANAGEMENT_AGREEMENT_DOCUMENT));
        mproperty.put(BELONG_TO_CATEGORY_PROPERTY_OTHERS, commonService.findListAttachmentByBelong(id, BELONG_TO_CATEGORY_PROPERTY_OTHERS));
        mproperty.put(BELONG_TO_CATEGORY_PROPERTY_MAIN_IMAGE, commonService.findListAttachmentByBelong(id, BELONG_TO_CATEGORY_PROPERTY_MAIN_IMAGE));
        mproperty.put(BELONG_TO_CATEGORY_PROPERTY_BANK_CARD_PICTURE, commonService.findListAttachmentByBelong(id, BELONG_TO_CATEGORY_PROPERTY_BANK_CARD_PICTURE));
        return mproperty;
    }
}